package pathfinder

/*
#cgo windows LDFLAGS: -L${SRCDIR} -lPathLibwin -lm -lstdc++
#cgo linux LDFLAGS: -L${SRCDIR} -lPathLibLinux -lm -lstdc++
#cgo darwin LDFLAGS: -L${SRCDIR} -lPathLibMac -lm -lstdc++
#include "BridgeCpp.h"
#include <stdio.h>
#include <stdlib.h>
*/
import "C"
import (
	"src/zeus/linmath"
	"src/zeus/logger"
	"unsafe"
)

type Cgo_dtNavMesh C.dtNavMesh
type cgo_dtNavfinder C.PathFinder
type Cgo_TempObstaclesNavMesh C.TempObstaclesNavMesh
type Cgo_ObsNavMesh C.ObsNavMesh
type Cgo_ObsPathFinder C.ObsPathFinder

// 获取Navmesh
func GetNavMesh(name string) *Cgo_dtNavMesh {
	return (*Cgo_dtNavMesh)(C.GetNavMesh(C.CString(name)))
}

// 生成finder
func GetNavFinder(dtnavmesh *Cgo_dtNavMesh) *cgo_dtNavfinder {
	return (*cgo_dtNavfinder)(C.GetFinder((*C.dtNavMesh)(dtnavmesh)))
}

// 释放所有存好的Navmesh
func ReleaseNavFile() {
	C.ReleaseMap()
}

// 查找路径
func FindNavPath(finder *cgo_dtNavfinder, spos *linmath.Vector3, epos *linmath.Vector3, count *int32) *C.float {
	return C.FindPath((*C.PathFinder)(finder), C.float(spos.X), C.float(spos.Y), C.float(spos.Z), C.float(epos.X), C.float(epos.Y), C.float(epos.Z), (*C.int)(unsafe.Pointer(count)))
}

// 获取导航附近的点
func CalcNavNear(finder *cgo_dtNavfinder, spos *linmath.Vector3, count *int32) *C.float {
	return C.CalcNear((*C.PathFinder)(finder), C.float(spos.X), C.float(spos.Y), C.float(spos.Z), (*C.int)(unsafe.Pointer(count)))
}

// CalcRaycast 射线检测
func CalcRaycast(finder *cgo_dtNavfinder, spos *linmath.Vector3, epos *linmath.Vector3, count *int32) *C.float {
	return C.CalcRaycast((*C.PathFinder)(finder), C.float(spos.X), C.float(spos.Y), C.float(spos.Z), C.float(epos.X), C.float(epos.Y), C.float(epos.Z), (*C.int)(unsafe.Pointer(count)))
}
func FreeNavMesh(finder *cgo_dtNavfinder) {
	C.FreeNavMesh((*C.PathFinder)(finder))
}
func Free(ptr unsafe.Pointer) {
	C.free(ptr)
}

// /////////////////////////////////////////////////////////////
// 获取Navmesh temp obstacles
func GetNavMeshTO(name string) *Cgo_TempObstaclesNavMesh {
	return (*Cgo_TempObstaclesNavMesh)(C.GetNavMeshTO(C.CString(name)))
}

// 释放所有存好的Navmesh
func ReleaseNavFileTO() {
	C.ReleaseMapTO()
}

// 查找路径
func FindNavPathTO(finder *Cgo_TempObstaclesNavMesh, spos *linmath.Vector3, epos *linmath.Vector3, count *int32) *C.float {
	return C.FindPathTO((*C.TempObstaclesNavMesh)(finder), C.float(spos.X), C.float(spos.Y), C.float(spos.Z), C.float(epos.X), C.float(epos.Y), C.float(epos.Z), (*C.int)(unsafe.Pointer(count)))
}

func FindNavPathExTO(finder *Cgo_TempObstaclesNavMesh, spos *linmath.Vector3, epos *linmath.Vector3) bool {
	if C.FindPathExTO((*C.TempObstaclesNavMesh)(finder), C.float(spos.X), C.float(spos.Y), C.float(spos.Z), C.float(epos.X), C.float(epos.Y), C.float(epos.Z)) == 0 {
		return false
	}
	return true
}

func GetNavPath(finder *Cgo_TempObstaclesNavMesh, count *int32) *C.float {
	return C.GetPath((*C.TempObstaclesNavMesh)(finder), (*C.int)(unsafe.Pointer(count)))
}

// CalcNavNearTO 获取导航附近的点
func CalcNavNearTO(finder *Cgo_TempObstaclesNavMesh, spos *linmath.Vector3, count *int32) *C.float {
	return C.CalcNearTO((*C.TempObstaclesNavMesh)(finder), C.float(spos.X), C.float(spos.Y), C.float(spos.Z), (*C.int)(unsafe.Pointer(count)))
}

// AddCyinderTO 增加动态阻挡
func AddCyinderTO(finder *Cgo_TempObstaclesNavMesh, tag string, spos *linmath.Vector3, radius float32, height float32) {
	C.AddCylinderTO((*C.TempObstaclesNavMesh)(finder), C.CString(tag), C.float(spos.X), C.float(spos.Y), C.float(spos.Z), C.float(radius), C.float(height))
}

// AddObbBox 增加OBB动态阻挡Box
func AddObbBoxTO(finder *Cgo_TempObstaclesNavMesh, tag string, centPos, halfPos *linmath.Vector3, rotaY float32) {
	C.AddObbBox((*C.TempObstaclesNavMesh)(finder), C.CString(tag), C.float(centPos.X), C.float(centPos.Y), C.float(centPos.Z),
		C.float(halfPos.X), C.float(halfPos.Y), C.float(halfPos.Z), C.float(rotaY))

}

func AddAabbBox(finder *Cgo_TempObstaclesNavMesh, tag string, minPos, maxPos *linmath.Vector3) {
	C.AddAabbBox((*C.TempObstaclesNavMesh)(finder), C.CString(tag), C.float(minPos.X), C.float(minPos.Y), C.float(minPos.Z),
		C.float(maxPos.X), C.float(maxPos.Y), C.float(maxPos.Z))
}

// RemoveTOByTag 删除动态阻挡
func RemoveTOByTag(finder *Cgo_TempObstaclesNavMesh, tag string) {
	C.RemoveTOByTag((*C.TempObstaclesNavMesh)(finder), C.CString(tag))
}

func RemoveAllTO(finder *Cgo_TempObstaclesNavMesh) {
	C.RemoveAllTO((*C.TempObstaclesNavMesh)(finder))
}

// UpdateTO 更新临时阻挡信息
func UpdateTO(finder *Cgo_TempObstaclesNavMesh) {
	C.Update((*C.TempObstaclesNavMesh)(finder))
}

func FreeToNavMesh(finder *Cgo_TempObstaclesNavMesh) {
	C.FreeToNavMesh((*C.TempObstaclesNavMesh)(finder))
}

// CalcNavNearTO 计算射线检测
func CalcRaycastTO(finder *Cgo_TempObstaclesNavMesh, spos *linmath.Vector3, epos *linmath.Vector3, count *int32) *C.float {
	return C.CalcRaycastTO((*C.TempObstaclesNavMesh)(finder), C.float(spos.X), C.float(spos.Y), C.float(spos.Z), C.float(epos.X), C.float(epos.Y), C.float(epos.Z), (*C.int)(unsafe.Pointer(count)))
}

//-----------------------------------------------------------------------------

func newObsNavMesh(filename, key string) (navmesh *Cgo_ObsNavMesh) {
	defer func() {
		logger.Debugf(logger.LogKey_Lib, "newObsNavMesh(%s,%s) %p", filename, key, navmesh)
	}()
	return (*Cgo_ObsNavMesh)(C.NewObsNavMesh(C.CString(filename), C.CString(key)))
}

func newObsPathFinder(mesh *Cgo_ObsNavMesh) *Cgo_ObsPathFinder {
	logger.Debugf(logger.LogKey_Lib, "newObsPathFinder(%p)", mesh)
	return (*Cgo_ObsPathFinder)(C.NewObsPathFinder((*C.ObsNavMesh)(mesh)))
}

func (finder *Cgo_ObsPathFinder) FreeObsPath() {
	logger.Debugf(logger.LogKey_Lib, "FreeObsPath(%p)", finder)
	C.FreeObsPath((*C.ObsPathFinder)(finder))
}

// AddCyinderTO 增加动态阻挡
func (mesh *Cgo_ObsNavMesh) ObsAddCylinder(tag string, spos *linmath.Vector3, radius float32, height float32) {
	C.ObsAddCylinder((*C.ObsNavMesh)(mesh), C.CString(tag), C.float(spos.X), C.float(spos.Y), C.float(spos.Z), C.float(radius), C.float(height))
}

// AddObbBox 增加OBB动态阻挡Box
func (mesh *Cgo_ObsNavMesh) ObsAddObbBox(tag string, centPos, halfPos *linmath.Vector3, rotaY float32) {
	C.ObsAddObbBox((*C.ObsNavMesh)(mesh), C.CString(tag), C.float(centPos.X), C.float(centPos.Y), C.float(centPos.Z),
		C.float(halfPos.X), C.float(halfPos.Y), C.float(halfPos.Z), C.float(rotaY))
}

func (mesh *Cgo_ObsNavMesh) ObsAddAabbBox(tag string, minPos, maxPos *linmath.Vector3) {
	C.ObsAddAabbBox((*C.ObsNavMesh)(mesh), C.CString(tag), C.float(minPos.X), C.float(minPos.Y), C.float(minPos.Z),
		C.float(maxPos.X), C.float(maxPos.Y), C.float(maxPos.Z))
}

// RemoveTOByTag 删除动态阻挡
func (mesh *Cgo_ObsNavMesh) ObsRemoveTOByTag(tag string) {
	C.ObsRemoveTOByTag((*C.ObsNavMesh)(mesh), C.CString(tag))
}

func (mesh *Cgo_ObsNavMesh) ObsRemoveAllTO() {
	C.ObsRemoveAllTO((*C.ObsNavMesh)(mesh))
}

// UpdateTO 更新临时阻挡信息
func (mesh *Cgo_ObsNavMesh) ObsUpdateTO() {
	C.ObsUpdate((*C.ObsNavMesh)(mesh))
}

// 查找路径
func (finder *Cgo_ObsPathFinder) FindNavPath(spos *linmath.Vector3, epos *linmath.Vector3, count *int32) *C.float {
	return C.ObsFindPath((*C.ObsPathFinder)(finder), C.float(spos.X), C.float(spos.Y), C.float(spos.Z), C.float(epos.X), C.float(epos.Y), C.float(epos.Z), (*C.int)(unsafe.Pointer(count)))
}

// 获取导航附近的点
func (finder *Cgo_ObsPathFinder) CalcNavNear(spos *linmath.Vector3, count *int32) *C.float {
	return C.ObsCalcNear((*C.ObsPathFinder)(finder), C.float(spos.X), C.float(spos.Y), C.float(spos.Z), (*C.int)(unsafe.Pointer(count)))
}

// CalcRaycast 射线检测
func (finder *Cgo_ObsPathFinder) CalcRaycast(spos *linmath.Vector3, epos *linmath.Vector3, count *int32) *C.float {
	return C.ObsCalcRaycast((*C.ObsPathFinder)(finder), C.float(spos.X), C.float(spos.Y), C.float(spos.Z), C.float(epos.X), C.float(epos.Y), C.float(epos.Z), (*C.int)(unsafe.Pointer(count)))
}
